"""
Functions to read in data from Mettler Toldedo balances using serial connections.
"""

import serial
import datetime
import pandas as pd
from time import sleep
from pdb import set_trace

def monitor(port=0, baudrate=2400, bytesize=7, parity='E', dt=1, fname='mt.dat', totalt=1e10):
    """ 
    General function to open a serial connection to a Mettler Toledo balance
    and read the mass at a specified frequency and save data to file.
    port : port name on computer (see /dev/tty for available ports) 
            Note that the port must have write permission.
    baudrate : integer - baudrate of transfer (see manual to set or individual 
        functions to set)
    bytesize : integer - number of bits
    parity : string [E | N | O] parity check
    dt : float time delta (seconds) between reads
    fname : string of filename to save data
    totalt : float number of seconds to record data
    """
    ser = serial.Serial(port=port, baudrate=baudrate, bytesize=bytesize, parity=parity, timeout=1)
    with open(fname, mode='w') as fObj:
        fObj.write("Date Time Mass(g) \r\n")
        start = datetime.datetime.now()
        t = datetime.datetime.now()
        delta = t - start
        while delta.seconds < totalt:
            """ Get the instantaneous balance value 
            (See Mettler Toledo Standard Interface Command Set page 19)"""
            ser.write(u'SI\r\n')
            sleep(dt)
            resp = ser.readline()
            mass = resp.split(" ")[-2]
            data = " ".join([str(t), str(mass), "\r\n"])
            fObj.write(data)
            fObj.flush()
            t = datetime.datetime.now()
            delta = t - start
        fObj.close()

def monitor_PG5002(port=0, baudrate=2400, bytesize=7, parity='E', dt=1, fname='mt.dat'):
    """ 
    Open a serial connection with settings required by the Mettler Toledo
    PG5002-S DeltaRange balance.
    To determine serial connections:
        1. Turn balance on
        2. press and hold menu
        3. press menu until the following are shown
            bd   2400   -  indicates the baudrate is 2400
            7b-E        -  indicates that 7 bits, and even parity
            HS oFF      -  indicates handshaking is off
    port : port number on computer
    dt : time delta between reads
    fname : string of filename to save data
    """
    monitor(port=port, baudrate=2400, bytesize=7, parity='E', dt=dt, fname=fname)

def monitor_MX5(port=0, dt=1, fname='mt.dat'):
    """ 
    Open a serial connection with settings required by the Mettler Toledo
    MX5 balance.
    To determine serial connections:
        1. Press the printer icon
        2. Navigate to the serial connection information
    port : port number on computer
    dt : time delta between reads
    fname : string of filename to save data
    """
    monitor(port=port, baudrate=9600, bytesize=8, parity='N', dt=dt, fname=fname)

def read_data(fname):
    """
    Read and parse the data file.
    fname : string of path name to data file
    """
    df = pd.read_csv(fname, sep=" ", header=0)
    del df['Unnamed: 3']
    df['Time'] = pd.to_datetime(df['Date'] + " " + df['Time'],
            format="%Y-%m-%d %H:%M:%S.%f")
    del df['Date']
    return df

def make_plot(fname):
    """
    Plot the contenst of a text file collected from the qcm
    function.
    fname : string of path name to data file
    return : matplotlib.AxesSubplot
    """
    df = read_data(fname)
    df['Delta'] = df['Time'] - df['Time'][0]
    df['Delta'] = [float(d)/(1.e9 * 3600) for d in df['Delta']]
    ax = df.plot(x='Delta', y='Mass(g)')
    ax.set_xlabel(r'$\Delta$ t (hr)')
    ax.set_ylabel(r'm (g)')
    return 

if __name__ == "__main__":
    import sys
    if sys.argv[1] == "PG5002":
        monitor_PG5002()
    elif sys.argv[1] == "MX5":
        monitor_MX5()
